home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fatted Calf
/
The Fatted Calf.iso
/
Applications
/
Astronomy
/
Moon
/
Source
/
shadow.c
< prev
Wrap
Text File
|
1993-01-19
|
4KB
|
116 lines
/* shadow.c
* Part of the Moon application for the NeXT computer.
* Author: Geoffrey S. Knauth
* Date: January 4, 1992
*
* Permission to copy this program is hereby granted under the terms
* of the Free Software Foundation's GNU General Public License.
*/
#import <dpsclient/event.h> /* NXPoint */
#import <dpsclient/psops.h> /* PSsetgray */
#import "all.h"
void DrawMoonShadow /* draw moon shadow, independent of view */
(float phase, /* phase of the moon */
NXPoint *center, /* pixel center of moon */
float xradius, /* half width of moon in pixels */
float yradius, /* half height of moon in pixels */
int shadowColor) /* color to use in drawing shadow */
{
/* DrawMoonShadow is called from within drawSelf:: methods of various
* view types. Postscript focus locking and unlocking are outside
* of this function.
*/
float yDown, yUp;
int i, up, down, oneSideHalf, numLeftSidePoints, numRightSidePoints;
NXPoint *leftSide, *rightSide; /* storage for lists of NXPoints */
double d, amp, xscale;
/* the number of points in the top half on one side is
* oneSideHalf = center+1..top,
* = (top - (center+1) + 1), or (top - center);
*/
oneSideHalf = rint(yradius);
/* make sure oneSideHalf is >= 0 */
if (oneSideHalf < 0) oneSideHalf = 0;
/* calculate the number of points on each side
* remember to add a point for the center
*/
numLeftSidePoints = numRightSidePoints = 1 + 2 * oneSideHalf;
/* allocate the points */
leftSide = calloc(numLeftSidePoints, sizeof(NXPoint));
rightSide = calloc(numRightSidePoints, sizeof(NXPoint));
/* Now iterate from the center to the bottom, filling in information
* for the left and right sides.
* Remember to calculate the region to black out, not whiten.
* As we fill in points for the bottom half, we know that the points
* for the top half will be a mirror image, so we can just copy them.
*/
xscale = cos(2 * PI * phase);
for (i = 0, /* variable controlling loop */
down = oneSideHalf, /* index into arrays of NXPoint */
yDown = yUp = center->y; /* diverging y values for halves */
i <= oneSideHalf; /* stop when bottom half done */
i++, /* 0..oneSideHalf-1 */
down++, /* oneSideHalf..bottom index */
yDown -= 1., /* float y for drawing bottom half */
yUp += 1.) /* float y for drawing upper half */
{
if ((d = i / yradius) > 1.0)
d = 1.0;
amp = xradius * cos(asin(d)); /* d > 1.0 yields NaN (not a number) */
/* 0.0 = new moon, 0.5 full moon, 1.0 = next new moon */
if (phase < 0.5) { /* waxing */
leftSide[down].x = center->x - amp;
rightSide[down].x = center->x + xscale * amp;
} else { /* waning */
rightSide[down].x = center->x + amp;
leftSide[down].x = center->x - xscale * amp;
}
leftSide[down].y = rightSide[down].y = yDown;
if (i) { /* # points offset downward from center */
up = down - 2 * i;
leftSide[up].x = leftSide[down].x;
rightSide[up].x = rightSide[down].x;
leftSide[up].y = rightSide[up].y = yUp;
}
}
/* Now iterate again from the top, this time actually creating
* a path clockwise around the points just calculated.
*/
PSnewpath();
PSmoveto(rightSide[0].x, rightSide[0].y);
/* Go down the right side, starting with the second point, because we
* just moved to the top point.
*/
for (i = 1; i < numRightSidePoints; i++)
PSlineto(rightSide[i].x, rightSide[i].y);
/* Now go up the left side, starting again with the second point, because
* we just reached the bottom, and stop one short of the top, because we
* started with the top when we started down in the first place.
*/
for (i = numLeftSidePoints - 2; i > 0; i--)
PSlineto(leftSide[i].x, leftSide[i].y);
PSclosepath();
/* draw the moon shadow, that part of the moon hidden from the sun */
PSsetgray(shadowColor);
PSfill();
/* deallocate the points */
free((char *) leftSide);
free((char *) rightSide);
}